﻿using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEditor.AnimatedValues;
using UnityEditor.UI;
using UnityEngine.UI;

namespace SoarD.Editor.UI
{
    [CustomEditor(typeof(SDImageBase), true)]
    [CanEditMultipleObjects]
    public class SDImageBaseEditor : GraphicEditor
    {
        SerializedProperty m_FillMethod;
        SerializedProperty m_FillOrigin;
        SerializedProperty m_FillAmount;
        SerializedProperty m_FillClockwise;
        protected SerializedProperty m_Type;
        SerializedProperty m_FillCenter;
        protected SerializedProperty m_UseSpritePacker;
        protected SerializedProperty m_SpriteName;
        protected SerializedProperty m_Sprite;
        protected SerializedProperty m_PreserveAspect;
        SerializedProperty m_Mask;
        GUIContent m_UseSpritePackerContent;
        GUIContent m_SpriteNameContent;
        GUIContent m_SpriteContent;
        GUIContent m_SpriteTypeContent;
        GUIContent m_ClockwiseContent;
        GUIContent m_MaskContent;

        AnimBool m_ShowSlicedOrTiled;
        AnimBool m_ShowSliced;
        AnimBool m_ShowFilled;
        protected AnimBool m_ShowType;
        
        #region 自定义
        SerializedProperty m_ShapeType;
        GUIContent m_ShapeTypeContent;
        SerializedProperty m_ShapeAnchors;
        SerializedProperty m_ShapeAnchorsOffSet;
        SerializedProperty m_ShapeAnchorsCalPadding;
        SerializedProperty m_ShapeScale;
        SerializedProperty m_CircleShape_Segements;
        SerializedProperty m_CircleShape_FillPercent;
        SerializedProperty m_RectangleShape_CutMode;
        protected AnimBool m_ShowShapeType;
        AnimBool m_ShowCommonShapeType;
        AnimBool m_ShowSquareShape;
        AnimBool m_ShowCircleShape;
        AnimBool m_ShowRectangleShape;
        #endregion
        protected override void OnEnable()
        {
            base.OnEnable();

            m_UseSpritePackerContent = new GUIContent("UseSpritePacker");
            m_SpriteNameContent = new GUIContent("Sprite Name");
            m_SpriteContent = new GUIContent("Source Image");
            m_SpriteTypeContent = new GUIContent("Image Type");
            m_ClockwiseContent = new GUIContent("Clockwise");
            m_MaskContent = new GUIContent("Mask");

            m_UseSpritePacker = serializedObject.FindProperty("m_UseSpritePacker");
            m_SpriteName = serializedObject.FindProperty("m_SpriteName");
            m_Sprite = serializedObject.FindProperty("m_Sprite");
            m_Type = serializedObject.FindProperty("m_Type");
            m_FillCenter = serializedObject.FindProperty("m_FillCenter");
            m_FillMethod = serializedObject.FindProperty("m_FillMethod");
            m_FillOrigin = serializedObject.FindProperty("m_FillOrigin");
            m_FillClockwise = serializedObject.FindProperty("m_FillClockwise");
            m_FillAmount = serializedObject.FindProperty("m_FillAmount");
            m_PreserveAspect = serializedObject.FindProperty("m_PreserveAspect");
            m_Mask = serializedObject.FindProperty("m_Mask");

            m_ShowType = new AnimBool(m_Sprite.objectReferenceValue != null);
            m_ShowType.valueChanged.AddListener(Repaint);

            var typeEnum = (Image.Type)m_Type.enumValueIndex;

            m_ShowSlicedOrTiled = new AnimBool(!m_Type.hasMultipleDifferentValues && typeEnum == Image.Type.Sliced);
            m_ShowSliced = new AnimBool(!m_Type.hasMultipleDifferentValues && typeEnum == Image.Type.Sliced);
            m_ShowFilled = new AnimBool(!m_Type.hasMultipleDifferentValues && typeEnum == Image.Type.Filled);
            m_ShowSlicedOrTiled.valueChanged.AddListener(Repaint);
            m_ShowSliced.valueChanged.AddListener(Repaint);
            m_ShowFilled.valueChanged.AddListener(Repaint);
            SetShowNativeSize(true);

            #region 自定义
            m_ShapeTypeContent = new GUIContent("Shape Type");

            m_ShapeType = serializedObject.FindProperty("m_ShapeType");
            m_ShapeAnchors = serializedObject.FindProperty("m_ShapeAnchors");
            m_ShapeAnchorsOffSet = serializedObject.FindProperty("m_ShapeAnchorsOffSet");
            m_ShapeAnchorsCalPadding = serializedObject.FindProperty("m_ShapeAnchorsCalPadding");
            m_ShapeScale = serializedObject.FindProperty("m_ShapeScale");
            m_CircleShape_Segements = serializedObject.FindProperty("m_CircleShape_Segements");
            m_CircleShape_FillPercent = serializedObject.FindProperty("m_CircleShape_FillPercent");
            m_RectangleShape_CutMode = serializedObject.FindProperty("m_RectangleShape_CutMode");

            var shapeTypeEnum = (SDImage.ShapeType)m_ShapeType.enumValueIndex;
            m_ShowShapeType = new AnimBool(m_Sprite.objectReferenceValue != null && (Image.Type)m_Type.enumValueIndex == Image.Type.Simple);
            m_ShowShapeType.valueChanged.AddListener(Repaint);
            m_ShowCommonShapeType = new AnimBool(shapeTypeEnum == SDImage.ShapeType.Square || shapeTypeEnum == SDImage.ShapeType.Circle || shapeTypeEnum == SDImage.ShapeType.Rectangle);
            m_ShowCommonShapeType.valueChanged.AddListener(Repaint);
            m_ShowSquareShape = new AnimBool(shapeTypeEnum == SDImage.ShapeType.Square);
            m_ShowSquareShape.valueChanged.AddListener(Repaint);
            m_ShowCircleShape = new AnimBool(shapeTypeEnum == SDImage.ShapeType.Circle);
            m_ShowCircleShape.valueChanged.AddListener(Repaint);
            m_ShowRectangleShape = new AnimBool(shapeTypeEnum == SDImage.ShapeType.Rectangle);
            m_ShowRectangleShape.valueChanged.AddListener(Repaint);
            #endregion
        }

        protected override void OnDisable()
        {
            m_ShowType.valueChanged.RemoveListener(Repaint);
            m_ShowSlicedOrTiled.valueChanged.RemoveListener(Repaint);
            m_ShowSliced.valueChanged.RemoveListener(Repaint);
            m_ShowFilled.valueChanged.RemoveListener(Repaint);
            #region 自定义
            m_ShowShapeType.valueChanged.RemoveListener(Repaint);
            m_ShowCommonShapeType.valueChanged.RemoveListener(Repaint);
            m_ShowSquareShape.valueChanged.RemoveListener(Repaint);
            m_ShowCircleShape.valueChanged.RemoveListener(Repaint);
            m_ShowRectangleShape.valueChanged.RemoveListener(Repaint);
            #endregion
        }

        public override void OnInspectorGUI()
        {
            serializedObject.Update();
            SpriteGUI();
            AppearanceControlsGUI();
            RaycastControlsGUI();

            SDImage image = target as SDImage;
            m_ShowType.target = m_Sprite.objectReferenceValue != null;

            if (m_UseSpritePacker.boolValue)
            {
                image.material = null;
            }
            else
            {
                if (m_UseSpritePacker.boolValue != image.UseSpritePacker)
                {
                    ResetBySprite();
                }
                else
                {
                    if (m_Sprite.objectReferenceValue != image.sprite)
                    {
                        ResetBySprite();
                    }

                    if (!string.IsNullOrEmpty(image.SpriteName) && !image.SpriteName.Equals(m_SpriteName.stringValue))
                    {
                        ResetSprite(m_SpriteName.stringValue);
                    }
                }
            }

            if (EditorGUILayout.BeginFadeGroup(m_ShowType.faded))
                TypeGUI();
            EditorGUILayout.EndFadeGroup();

            SetShowNativeSize(false);
            if (EditorGUILayout.BeginFadeGroup(m_ShowNativeSize.faded))
            {
                EditorGUI.indentLevel++;
                EditorGUILayout.PropertyField(m_PreserveAspect);
                EditorGUI.indentLevel--;
            }
            EditorGUILayout.EndFadeGroup();

            if (image.sprite != null && (image.sprite.border.w < 0 || image.sprite.border.x < 0 || image.sprite.border.y < 0 || image.sprite.border.z < 0))
            {
                EditorGUILayout.HelpBox("The Image have a error border.", MessageType.Error);
            }
            
            #region 自定义
            m_ShowShapeType.target = m_Sprite.objectReferenceValue != null && (Image.Type)m_Type.enumValueIndex == Image.Type.Simple;
            if (EditorGUILayout.BeginFadeGroup(m_ShowShapeType.faded))
                ShapeTypeGUI();
            EditorGUILayout.EndFadeGroup();
            #endregion

            NativeSizeButtonGUI();

            if (image.UseSpritePacker)
            {
                EditorGUILayout.HelpBox("当前非TP模式，请记得修改.", MessageType.Info);
            }
            serializedObject.ApplyModifiedProperties();
        }

        protected void ResetBySprite()
        {
            SDImage image = target as SDImage;
            image.SpriteName = m_Sprite.objectReferenceValue ? m_Sprite.objectReferenceValue.name : "";
            m_SpriteName.stringValue = image.SpriteName;
            ResetSprite(image.SpriteName);
        }

        protected void ResetSprite(string spriteName)
        {
            Material mat;
            Sprite sprite = SDUIUtility.FindTPSprite(spriteName, out mat);
            m_Material.objectReferenceValue = mat;
            m_Sprite.objectReferenceValue = sprite;
        }

        protected void SetShowNativeSize(bool instant)
        {
            SetShowNativeSize(true, instant);
        }

        protected void SpriteGUI()
        {
            SDImage image = target as SDImage;
            EditorGUI.BeginChangeCheck();
            if(image.canvasRenderer.cull){
                EditorGUILayout.LabelField("cull:true");
            }
            else{
                EditorGUILayout.LabelField("cull:false");
            }
            EditorGUILayout.PropertyField(m_UseSpritePacker, m_UseSpritePackerContent);
            if (!image.UseSpritePacker)
            {
                EditorGUILayout.PropertyField(m_SpriteName, m_SpriteNameContent);
            }
            EditorGUILayout.PropertyField(m_Sprite, m_SpriteContent);
            EditorGUILayout.PropertyField(m_Mask, m_MaskContent);
            if (EditorGUI.EndChangeCheck())
            {
                var newSprite = m_Sprite.objectReferenceValue as Sprite;
                if (newSprite)
                {
                    Image.Type oldType = (Image.Type)m_Type.enumValueIndex;
                    if (newSprite.border.SqrMagnitude() > 0)
                    {
                        m_Type.enumValueIndex = (int)Image.Type.Sliced;
                    }
                    else if (oldType == Image.Type.Sliced)
                    {
                        m_Type.enumValueIndex = (int)Image.Type.Simple;
                    }
                }
            }
        }

        protected void TypeGUI()
        {
            EditorGUILayout.PropertyField(m_Type, m_SpriteTypeContent);

            ++EditorGUI.indentLevel;
            {
                Image.Type typeEnum = (Image.Type)m_Type.enumValueIndex;

                bool showSlicedOrTiled = (!m_Type.hasMultipleDifferentValues && (typeEnum == Image.Type.Sliced || typeEnum == Image.Type.Tiled));
                if (showSlicedOrTiled && targets.Length > 1)
                    showSlicedOrTiled = targets.Select(obj => obj as Image).All(img => img.hasBorder);

                m_ShowSlicedOrTiled.target = showSlicedOrTiled;
                m_ShowSliced.target = (showSlicedOrTiled && !m_Type.hasMultipleDifferentValues && typeEnum == Image.Type.Sliced);
                m_ShowFilled.target = (!m_Type.hasMultipleDifferentValues && typeEnum == Image.Type.Filled);

                Image image = target as Image;
                
                if (EditorGUILayout.BeginFadeGroup(m_ShowSlicedOrTiled.faded))
                {
                    if (image.hasBorder)
                        EditorGUILayout.PropertyField(m_FillCenter);
                }
                EditorGUILayout.EndFadeGroup();

                if (EditorGUILayout.BeginFadeGroup(m_ShowSliced.faded))
                {
                    if (image.sprite != null && !image.hasBorder)
                    {
                        EditorGUILayout.HelpBox("The Image doesn't have a border.", MessageType.Error);
                    }
                }
                EditorGUILayout.EndFadeGroup();

                if (EditorGUILayout.BeginFadeGroup(m_ShowFilled.faded))
                {
                    EditorGUI.BeginChangeCheck();
                    EditorGUILayout.PropertyField(m_FillMethod);
                    if (EditorGUI.EndChangeCheck())
                    {
                        m_FillOrigin.intValue = 0;
                    }
                    switch ((Image.FillMethod)m_FillMethod.enumValueIndex)
                    {
                        case Image.FillMethod.Horizontal:
                            m_FillOrigin.intValue = (int)(Image.OriginHorizontal)EditorGUILayout.EnumPopup("Fill Origin", (Image.OriginHorizontal)m_FillOrigin.intValue);
                            break;
                        case Image.FillMethod.Vertical:
                            m_FillOrigin.intValue = (int)(Image.OriginVertical)EditorGUILayout.EnumPopup("Fill Origin", (Image.OriginVertical)m_FillOrigin.intValue);
                            break;
                        case Image.FillMethod.Radial90:
                            m_FillOrigin.intValue = (int)(Image.Origin90)EditorGUILayout.EnumPopup("Fill Origin", (Image.Origin90)m_FillOrigin.intValue);
                            break;
                        case Image.FillMethod.Radial180:
                            m_FillOrigin.intValue = (int)(Image.Origin180)EditorGUILayout.EnumPopup("Fill Origin", (Image.Origin180)m_FillOrigin.intValue);
                            break;
                        case Image.FillMethod.Radial360:
                            m_FillOrigin.intValue = (int)(Image.Origin360)EditorGUILayout.EnumPopup("Fill Origin", (Image.Origin360)m_FillOrigin.intValue);
                            break;
                    }
                    EditorGUILayout.PropertyField(m_FillAmount);
                    if ((Image.FillMethod)m_FillMethod.enumValueIndex > Image.FillMethod.Vertical)
                    {
                        EditorGUILayout.PropertyField(m_FillClockwise, m_ClockwiseContent);
                    }
                }
                EditorGUILayout.EndFadeGroup();
            }
            --EditorGUI.indentLevel;
        }
 #region 自定义
        protected void ShapeTypeGUI()
        {
            EditorGUILayout.PropertyField(m_ShapeType, m_ShapeTypeContent);

            SDImage.ShapeType typeEnum = (SDImage.ShapeType)m_ShapeType.enumValueIndex;
            // LImage image = target as LImage;

            ++EditorGUI.indentLevel;
            {
                m_ShowCommonShapeType.target = typeEnum == SDImage.ShapeType.Square || typeEnum == SDImage.ShapeType.Circle || typeEnum == SDImage.ShapeType.Rectangle;
                m_ShowSquareShape.target = (!m_ShapeType.hasMultipleDifferentValues && typeEnum == SDImage.ShapeType.Square);
                m_ShowCircleShape.target = (!m_ShapeType.hasMultipleDifferentValues && typeEnum == SDImage.ShapeType.Circle);
                m_ShowRectangleShape.target = (!m_ShapeType.hasMultipleDifferentValues && typeEnum == SDImage.ShapeType.Rectangle);

                if (EditorGUILayout.BeginFadeGroup(m_ShowRectangleShape.faded))
                {
                    EditorGUILayout.PropertyField(m_RectangleShape_CutMode, new GUIContent("Cut Mode"));
                }
                EditorGUILayout.EndFadeGroup();      

                if (EditorGUILayout.BeginFadeGroup(m_ShowCommonShapeType.faded))
                {
                    EditorGUILayout.PropertyField(m_ShapeAnchors,new GUIContent("Anchors"));
                    EditorGUILayout.PropertyField(m_ShapeAnchorsOffSet,new GUIContent("OffSet"));
                    EditorGUILayout.PropertyField(m_ShapeAnchorsCalPadding,new GUIContent("IncludePadding"));
                    if (m_ShapeAnchorsCalPadding.boolValue)
                    {
                        EditorGUILayout.HelpBox("计算Padding可能会截取到图集中其他像素，", MessageType.Warning);
                    }
                    EditorGUILayout.PropertyField(m_ShapeScale);
                }
                EditorGUILayout.EndFadeGroup();

                if (EditorGUILayout.BeginFadeGroup(m_ShowCircleShape.faded))
                {
                    EditorGUILayout.PropertyField(m_CircleShape_FillPercent);
                    EditorGUILayout.PropertyField(m_CircleShape_Segements);
                }
                EditorGUILayout.EndFadeGroup();      
            }
        }
        #endregion
        public override bool HasPreviewGUI() { return true; }
        public override void OnPreviewGUI(Rect rect, GUIStyle background)
        {
            SDImage image = target as SDImage;
            if (image == null) return;

            Sprite sf = image.sprite;
            if (sf == null) return;

            SpriteDrawUtility.DrawSprite(sf, rect, image.canvasRenderer.GetColor());
        }

        public override string GetInfoString()
        {
            Image image = target as Image;
            Sprite sprite = image.sprite;

            int x = (sprite != null) ? Mathf.RoundToInt(sprite.rect.width) : 0;
            int y = (sprite != null) ? Mathf.RoundToInt(sprite.rect.height) : 0;

            return string.Format("Image Size: {0}x{1}", x, y);
        }
    }
}
